import { 
  AmbientLight, 
  AxesHelper, 
  BoxGeometry, 
  Camera, 
  Color, 
  DirectionalLight, 
  Mesh, MeshLambertMaterial, 
  OrthographicCamera, 
  PerspectiveCamera, PlaneGeometry, Scene, SphereGeometry, 
  Vector3, 
  WebGLRenderer 
} from "three";
// @ts-ignore
import Stats from 'stats.js';
import { GUI } from 'dat.gui';

const scene = new Scene()
let camera: PerspectiveCamera | OrthographicCamera = new PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000)
// 设置相机位置
camera.position.set(120, 60, 180);

const renderer = new WebGLRenderer({ antialias: true })
renderer.setClearColor(0x000000)
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.shadowMap.enabled = true

document.body.appendChild(renderer.domElement)

// 创建一个平面
const planeGeometry = new PlaneGeometry(180, 180)
const planeMaterial = new MeshLambertMaterial({ color: 0xffffff })
const plane = new Mesh(planeGeometry, planeMaterial)
// 接收阴影
plane.receiveShadow = true

plane.rotation.x = -0.5 * Math.PI
plane.position.x = 0
plane.position.y = 0
plane.position.z = 0

scene.add(plane)

// 在平面上铺满矩形
let cubeGeometry = new BoxGeometry(4, 4, 4)
for (let j = 0; j < (planeGeometry.parameters.height / 5); j++) {
  for(let i = 0; i < (planeGeometry.parameters.width / 5); i++) {
    let rnd = Math.random() * 0.75 + 0.25
    let cubeMaterial = new MeshLambertMaterial()
    cubeMaterial.color = new Color(rnd, 0, 0)
    let cube = new Mesh(cubeGeometry, cubeMaterial)

    cube.position.z = -(planeGeometry.parameters.height / 2) + 2 + (j * 5)
    cube.position.x = -(planeGeometry.parameters.width / 2) + 2 + (i * 5)
    cube.position.y = 2

    scene.add(cube)
  }
}

let lookAtGeom = new SphereGeometry(2)
let lookAtMesh = new Mesh(lookAtGeom, new MeshLambertMaterial({
  color: 0x00ff00
}))
scene.add(lookAtMesh)

// 创建一个方向光
let directionalLight = new DirectionalLight(0xffffff, .7)
directionalLight.position.set(-20, 40, 60)
scene.add(directionalLight)

// 添加坐标系，方便理解
const axes = new AxesHelper(15)
scene.add(axes)

// 添加环境光
const ambientLight = new AmbientLight(0x292929)
scene.add(ambientLight)

// 添加 FPS 监控
let stats: Stats = new Stats()
stats.showPanel(0)
document.body.appendChild(stats.dom)

// 控制功能
let step = 0
let controls = {
  perspective: 'Perspective',
  switchCamera: function() {
    // 如果是透视相机
    if (camera instanceof PerspectiveCamera) {
      camera = new OrthographicCamera(
        window.innerWidth/ -16, 
        window.innerWidth / 16, 
        window.innerHeight / 16,
        window.innerHeight / -16,
        -200, 500
      )
      this.perspective = 'Orthographic'
    } 
    // 正投影相机时
    else {
      camera = new PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000)
      this.perspective = 'Perspective'
    }

    camera.position.set(120, 60, 180);
    camera.lookAt(scene.position);
  }
}

// 控制器
const gui = new GUI()
gui.add(controls, 'switchCamera').name('切换相机');
gui.add(controls, 'perspective').name('当前相机').listen();

function render() {
  stats.update()

  step += 0.01
  if (camera instanceof Camera) {
    let x = 10 + (100 * Math.sin(step))
    camera.lookAt(new Vector3(x, 10, 0))
    lookAtMesh.position.copy(new Vector3(x, 10, 0))
  }

  requestAnimationFrame(render)
  renderer.render(scene, camera)
}
render()